
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Diagnostics;
using System.Xml;

using Swaf;
using Swaf.BizObj;
using Swaf.Resource;

namespace Swaf.Call
{
    public class OptionCall : ICall
    {
        protected string m_id;
        protected ICall m_internalCall;
        protected string m_evaluationVal;
        protected XmlElement m_firstCallDef, m_secondCallDef;

        public OptionCall(string id, XmlElement initInfo)
        {
            m_id = id;
            m_evaluationVal = initInfo.GetAttribute("value");
            bool resolveImmediately = false;

			if (initInfo.HasAttribute("resolveImmediately"))
            {
                resolveImmediately = (string.Compare(initInfo.GetAttribute("resolveImmediately"), "true", true) == 0);
            }

            bool pastFirst = false;
            foreach (XmlNode node in initInfo.ChildNodes)
                if (node is XmlElement)
                    if (pastFirst)
                    {
                        m_secondCallDef = node as XmlElement;
                        break;
                    }
                    else
                    {
                        m_firstCallDef = node as XmlElement;
                        pastFirst = true;
                    }

            if (!initInfo.HasAttribute("value"))
                throw new CallException(string.Format("Invalid configuration for Option configuration on rule {0}, you must provide a value to decide which child call to use", id));
            if (m_secondCallDef == null)
                throw new CallException(string.Format("Invalid configuration for Option configuration on rule {0}.  Two child call elements must be configured", id));

            if (resolveImmediately)
            {
                // Call InternalCall prop to resolve the call
                ICall tmpCall = InternalCall;
            }
        }

        protected ICall InternalCall
        {
            get
            {
                if (m_internalCall == null)
                {
                    string val = Application.globalApp.resMgr.resolve(m_evaluationVal);
                    IClassFactory callFactory = Application.currentApp.factories["CallTypes"];
                    XmlElement el = (val != "") ? m_firstCallDef : m_secondCallDef;
                    m_internalCall = callFactory.createFromNickName(el.Name, m_id, el) as ICall;
                }
                Debug.Assert(m_internalCall != null);
                return m_internalCall;
            }
        }

        #region ICall Members

        public string Id
        {
            get { return InternalCall.Id; }
        }

        public CallParamOption ParamHandling
        {
            get
            {
                return InternalCall.ParamHandling;
            }
            set
            {
                InternalCall.ParamHandling = value;
            }
        }

        public bool WorksWithMultiCall
        {
            get { return InternalCall.WorksWithMultiCall; }
        }

        public object[] CallParams
        {
            get
            {
                return InternalCall.CallParams;
            }
            set
            {
                InternalCall.CallParams = value;
            }
        }

        public CallDistanceType CallDistance
        {
            get { return InternalCall.CallDistance; }
        }

        public string Method
        {
            get { return InternalCall.Method; }
        }

        public object call(params object[] p)
        {
            return InternalCall.call(p);
        }

        #endregion
    }
}
